package com.easylinkin.linkappapi.fillin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.easylinkin.linkappapi.common.model.RequestModel;
import com.easylinkin.linkappapi.common.service.CommonService;
import com.easylinkin.linkappapi.common.utils.excel.ExcelConstant;
import com.easylinkin.linkappapi.common.utils.excel.ExcelTools;
import com.easylinkin.linkappapi.common.utils.io.OutputStreamUtil;
import com.easylinkin.linkappapi.fillin.dto.PeopleNumAtFillinDto;
import com.easylinkin.linkappapi.fillin.dto.TenantPeopleNumAtFillinDto;
import com.easylinkin.linkappapi.fillin.entity.PeopleNumAtFillin;
import com.easylinkin.linkappapi.fillin.entity.vo.PeopleNumAtFillinVo;
import com.easylinkin.linkappapi.fillin.entity.vo.TenantPeopleNumAtFillinVo;
import com.easylinkin.linkappapi.fillin.mapper.PeopleNumAtFillinMapper;
import com.easylinkin.linkappapi.fillin.service.PeopleNumAtFillinService;
import com.easylinkin.linkappapi.security.context.LinkappUserContextProducer;
import com.easylinkin.linkappapi.security.entity.LinkappUser;
import com.easylinkin.linkappapi.security.mapper.LinkappUserMapper;
import com.easylinkin.linkappapi.tenant.entity.LinkappTenant;
import com.easylinkin.linkappapi.tenant.mapper.LinkappTenantMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import site.morn.rest.RestBuilders;
import site.morn.rest.RestMessage;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;

/**
 * PeopleNumAtFillin表服务实现类
 *
 * @author zhengwen
 * @date 2022/10/13
 */
@Slf4j
@Service("PeopleNumAtFillinService")
public class PeopleNumAtFillinServiceImpl extends ServiceImpl
        <PeopleNumAtFillinMapper, PeopleNumAtFillin> implements PeopleNumAtFillinService {
    @Resource
    private CommonService commonService;
    @Resource
    private LinkappUserContextProducer linkappUserContextProducer;

    @Resource
    private LinkappUserMapper linkappUserMapper;

    @Resource
    private LinkappTenantMapper linkappTenantMapper;

    @Override
    public boolean saveOne(PeopleNumAtFillin appPeopleNumAtFillin) {
        commonService.setCreateAndModifyInfo(appPeopleNumAtFillin);
        appPeopleNumAtFillin.setDeleteState(1);
        appPeopleNumAtFillin.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        validParamRequired(appPeopleNumAtFillin);
        validRepeat(appPeopleNumAtFillin);
        validParamFormat(appPeopleNumAtFillin);
        return save(appPeopleNumAtFillin);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateOne(PeopleNumAtFillin appPeopleNumAtFillin) {
        Assert.notNull(appPeopleNumAtFillin.getId(), "id不能为空");
        commonService.setModifyInfo(appPeopleNumAtFillin);
        //appPeopleNumAtFillin.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        validRepeat(appPeopleNumAtFillin);
        validParamFormat(appPeopleNumAtFillin);
        return updateById(appPeopleNumAtFillin);
    }

    @Override
    public IPage<PeopleNumAtFillin> selectPage(Page page, PeopleNumAtFillin appPeopleNumAtFillin) {
        //appPeopleNumAtFillin.setTenantId(linkappUserContextProducer.getNotNullCurrent().getTenantId());
        return baseMapper.selectPage(page, appPeopleNumAtFillin);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByIds(List<Long> idList) {
        return removeByIds(idList);
    }

    @Override
    public void export(PeopleNumAtFillin appPeopleNumAtFillin, HttpServletRequest request, HttpServletResponse
            response) {

        IPage<PeopleNumAtFillin> page = selectPage(new Page(0, -1), appPeopleNumAtFillin);
        List<PeopleNumAtFillin> records = page.getRecords();
        List
                <PeopleNumAtFillinVo> appPeopleNumAtFillinVos = new ArrayList<>();
        for (PeopleNumAtFillin expert : records) {
            appPeopleNumAtFillinVos.add(new PeopleNumAtFillinVo(expert));
        }

        String keyValue = "名称:name,租户id:tenantId";
        String title = "PeopleNumAtFillin导出数据";
        String fileName = title + ".xls";
        try {
            OutputStream outputStream = OutputStreamUtil
                    .getOutputStream(request, response, fileName);
            ExcelTools.exportExcel(outputStream, keyValue, appPeopleNumAtFillinVos, ExcelConstant.XLS, title);
            response.flushBuffer();
            outputStream.close();
        } catch (IOException e) {
            log.error("excel导出失败", e);
            throw new RuntimeException("excel导出失败！IOException异常" + e.getMessage());
        } catch (Exception e) {
            log.error("excel导出失败", e);
            throw new RuntimeException("excel导出失败！" + e.getMessage());
        }
    }

    @Override
    public RestMessage getLatestData(PeopleNumAtFillinVo peopleNumAtFillinVo) {
        LinkappUser linkappUser = linkappUserContextProducer.getNotNullCurrent();
        peopleNumAtFillinVo.setTenantId(linkappUser.getTenantId());

        PeopleNumAtFillinDto dto = new PeopleNumAtFillinDto();
        dto.setFillIn(false);

        QueryWrapper<PeopleNumAtFillin> qw = new QueryWrapper<>();
        qw.eq("tenant_id", linkappUser.getTenantId());
        Boolean distUser = peopleNumAtFillinVo.getDistUser();
        if (distUser != null && distUser) {
            qw.eq("creator", linkappUser.getId());
        }
        Date now = DateUtil.date();
        qw.ge("create_time", DateUtil.beginOfDay(now));
        qw.le("create_time", DateUtil.endOfDay(now));
        qw.orderByDesc("create_time");
        qw.last(" limit 1");
        List<PeopleNumAtFillin> latestList = baseMapper.selectList(qw);
        if (CollectionUtil.isNotEmpty(latestList)) {
            PeopleNumAtFillin peopleNumAtFillin = latestList.get(0);
            //查询创建用户
            LinkappUser createUser = linkappUserMapper.selectById(peopleNumAtFillin.getCreator());

            BeanUtil.copyProperties(peopleNumAtFillin, dto, CopyOptions.create().setIgnoreNullValue(true));
            dto.setCreateUser(createUser);
            dto.setFillIn(true);
        }

        return RestBuilders.successBuilder().data(dto).build();
    }

    @Override
    public RestMessage selectDtoPage(RequestModel<PeopleNumAtFillinVo> requestModel) {
        Page page = requestModel.getPage();
        PeopleNumAtFillinVo peopleNumAtFillinVo = requestModel.getCustomQueryParams();
        Boolean isBusiness = false;
        String tenantId = peopleNumAtFillinVo.getTenantId();
        if(peopleNumAtFillinVo != null){
            Integer enterpriseSourceType = peopleNumAtFillinVo.getEnterpriseSourceType();
            if (enterpriseSourceType != null && enterpriseSourceType.intValue() == 2){
                if(StringUtils.isBlank(tenantId)){
                    isBusiness = true;
                }
            }else{
                LinkappUser linkappUser = linkappUserContextProducer.getNotNullCurrent();
                if (StringUtils.isBlank(tenantId)) {
                    tenantId = linkappUser.getTenantId();
                }
                //根据tenant_id查询项目信息，如果名称为：武汉建工集团，表示是企业用户
                LinkappTenant tenantInfo = linkappTenantMapper.getById(tenantId);
                if (tenantInfo != null && "武汉建工集团".equals(tenantInfo.getPlatformProjectName())) {
                    isBusiness = true;
                }
            }
        }

        IPage dtoList = null;
        if (isBusiness) {
            //企业用户
            Date now = DateUtil.date();
            Date startTime = DateUtil.beginOfDay(now);
            Date endTime = DateUtil.endOfDay(now);
            peopleNumAtFillinVo.setStartTime(startTime);
            peopleNumAtFillinVo.setEndTime(endTime);
            dtoList = baseMapper.selectBusinessDtoPage(page, peopleNumAtFillinVo);
        } else {
            //项目用户
            peopleNumAtFillinVo.setTenantId(tenantId);
            dtoList = baseMapper.selectDtoPage(page, peopleNumAtFillinVo);
            //项目用户需要补全每天的,分页补全有bug，补全不能用分页
            //compDayFillinData(dtoList, peopleNumAtFillinVo);
        }

        //数据转换
        convertToTenantPeopleNumFillinVo(dtoList, isBusiness);

        return RestBuilders.successBuilder().data(dtoList).build();
    }

    private void compDayFillinData(IPage dtoList, PeopleNumAtFillinVo peopleNumAtFillinVo) {
        List ls = dtoList.getRecords();
        List finLs = new ArrayList();
        Map<String, PeopleNumAtFillinDto> mp = new HashMap<>();
        if (CollectionUtil.isNotEmpty(ls)) {
            //转map
            ls.stream().forEach(p -> {
                PeopleNumAtFillinDto dto = (PeopleNumAtFillinDto) p;
                Date createTime = dto.getCreateTime();
                String ctStr = DateUtil.format(createTime, DatePattern.NORM_DATE_FORMAT);
                mp.put(ctStr, dto);
            });
        }
        //补全
        Date startTime = peopleNumAtFillinVo.getStartTime();
        Date endTime = peopleNumAtFillinVo.getEndTime();
        while (endTime.after(startTime)) {
            String etStr = DateUtil.format(endTime, DatePattern.NORM_DATE_PATTERN);
            PeopleNumAtFillinDto dto = mp.get(etStr);
            if (dto == null) {
                dto = new PeopleNumAtFillinDto();
                dto.setFillIn(false);
                dto.setTenantId(peopleNumAtFillinVo.getTenantId());
                dto.setCreateTime(endTime);
            }
            finLs.add(dto);

            endTime = DateUtil.offsetDay(endTime, -1);
        }
        dtoList.setRecords(finLs);
    }

    /**
     * 数据转换
     *
     * @param dtoList    数据list
     * @param isBusiness 是否企业用户
     */
    private void convertToTenantPeopleNumFillinVo(IPage dtoList, Boolean isBusiness) {
        List ls = dtoList.getRecords();
        if (CollectionUtil.isNotEmpty(ls)) {
            List<TenantPeopleNumAtFillinVo> voLs = new ArrayList<>();
            ls.stream().forEach(p -> {
                TenantPeopleNumAtFillinVo vo = new TenantPeopleNumAtFillinVo();
                vo.setFillIn(false);
                if (isBusiness) {
                    TenantPeopleNumAtFillinDto businessDto = (TenantPeopleNumAtFillinDto) p;
                    vo.setCreateUser(businessDto.getCreateUser());
                    PeopleNumAtFillin fillin = businessDto.getPeopleNumAtFillin();
                    if (fillin != null) {
                        vo.setFillIn(true);
                        vo.setPeopleNumAtFillin(fillin);
                    }
                    LinkappTenant tenant = new LinkappTenant();
                    BeanUtil.copyProperties(businessDto, tenant, CopyOptions.create().setIgnoreNullValue(true));
                    vo.setTenantInfo(tenant);
                } else {
                    PeopleNumAtFillinDto dto = (PeopleNumAtFillinDto) p;
                    vo.setCreateUser(dto.getCreateUser());
                    PeopleNumAtFillin fillin = new PeopleNumAtFillin();
                    BeanUtil.copyProperties(dto, fillin, CopyOptions.create().setIgnoreNullValue(true));
                    if (fillin.getId() != null) {
                        vo.setFillIn(true);
                    }
                    vo.setPeopleNumAtFillin(fillin);
                    vo.setTenantInfo(dto.getTenantInfo());
                }
                voLs.add(vo);
            });
            dtoList.setRecords(voLs);
        }
    }

    @Override
    public RestMessage getBusinessUserStatus() {
        LinkappUser linkappUser = linkappUserContextProducer.getNotNullCurrent();
        String tenantId = linkappUser.getTenantId();

        PeopleNumAtFillinVo peopleNumAtFillinVo = new PeopleNumAtFillinVo();
        peopleNumAtFillinVo.setBusinessUser(false);
        //根据tenant_id查询项目信息，如果名称为：武汉建工集团，表示是企业用户
        LinkappTenant tenantInfo = linkappTenantMapper.getById(tenantId);

        if (tenantInfo != null && "武汉建工集团".equals(tenantInfo.getPlatformProjectName())) {
            //企业用户
            peopleNumAtFillinVo.setBusinessUser(true);
        }
        return RestBuilders.successBuilder().data(peopleNumAtFillinVo).build();
    }

    @Override
    public RestMessage businessDayFillinData(PeopleNumAtFillinVo peopleNumAtFillinVo) {
        Date startTime = peopleNumAtFillinVo.getStartTime();
        Date endTime = peopleNumAtFillinVo.getEndTime();
        if (startTime == null || endTime == null) {
            Date now = DateUtil.date();
            startTime = DateUtil.beginOfDay(now);
            endTime = DateUtil.endOfDay(now);
        }
        peopleNumAtFillinVo.setStartTime(startTime);
        peopleNumAtFillinVo.setEndTime(endTime);

        //项目数量，已填报、未填报
        AtomicReference<Integer> totalTenantNum = new AtomicReference<>(0);
        AtomicReference<Integer> fillinTenantNum = new AtomicReference<>(0);
        AtomicReference<Integer> noFillinTenantNum = new AtomicReference<>(0);

        //项目数量10年也到不了1w，懒得写统计sql了，就查出来遍历吧
        Page page = new Page<>(1, -1);
        IPage<TenantPeopleNumAtFillinDto> dtoList = baseMapper.selectBusinessDtoPage(page, peopleNumAtFillinVo);
        List<TenantPeopleNumAtFillinDto> ls = dtoList.getRecords();
        if (CollectionUtil.isNotEmpty(ls)) {
            ls.stream().forEach(p -> {
                PeopleNumAtFillin fillinData = p.getPeopleNumAtFillin();
                if (fillinData == null) {
                    noFillinTenantNum.getAndSet(noFillinTenantNum.get() + 1);
                } else {
                    fillinTenantNum.getAndSet(fillinTenantNum.get() + 1);
                }
                totalTenantNum.getAndSet(totalTenantNum.get() + 1);
            });
        }

        //今日填报情况
        PeopleNumAtFillin peopleNumAtFillin = baseMapper.businessDayFillinData(peopleNumAtFillinVo);

        //参数转换
        PeopleNumAtFillinVo vo = new PeopleNumAtFillinVo();
        BeanUtil.copyProperties(peopleNumAtFillin, vo, CopyOptions.create().setIgnoreNullValue(true));
        vo.setTotalTenantNum(totalTenantNum.get());
        vo.setNoFillinTenantNum(noFillinTenantNum.get());
        vo.setFillinTenantNum(fillinTenantNum.get());

        return RestBuilders.successBuilder().data(vo).build();
    }


    @Override
    public PeopleNumAtFillin getOneById(Serializable id) {
        return baseMapper.getOneById(id);
    }

    /**
     * 校验重复
     */
    private void validRepeat(PeopleNumAtFillin appPeopleNumAtFillin) {
        /* QueryWrapper<PeopleNumAtFillin> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", appPeopleNumAtFillin.getName());
        queryWrapper.eq("tenant_id", linkappUserContextProducer.getNotNullCurrent().getTenantId());
        List<PeopleNumAtFillin> list = baseMapper.selectList(queryWrapper);
        if (list.size() == 0) {
            return;
        }
        if (list.size() > 1) {
            throw new BusinessException("名称有重复");
        }
        if (ObjectUtils.isEmpty(appPeopleNumAtFillin.getId())) {
            throw new BusinessException("名称已存在");
        }
        if (!appPeopleNumAtFillin.getId().equals(list.get(0).getId())) {
            throw new BusinessException("名称已存在");
        }
                    */

    }


    /**
     * 校验参数必填
     */
    private void validParamRequired(PeopleNumAtFillin appPeopleNumAtFillin) {
        //Assert.notNull(appPeopleNumAtFillin, "参数为空");
        //Assert.isTrue(StringUtils.isNotBlank(appPeopleNumAtFillin.getName()), "名称为空");
    }

    /**
     * 校验参数格式
     */
    private void validParamFormat(PeopleNumAtFillin appPeopleNumAtFillin) {
        //Assert.isTrue(appPeopleNumAtFillin.getName() == null || appPeopleNumAtFillin.getName().length() <= 50,
        //        "名称超长");
    }
}

